#include "esp8266_eswin.h"

#define CLOCK_DRV_Delay           OS_DelayMs
#define CLOCK_DRV_GetMilliseconds OS_KernelGetTickCount

#define ESP8266_UART_INSTANCE (1U) // 根据实际硬件设置UART实例号
#define BUFFER_SIZE           512
#define MAX_RESPONSE_LENGTH   128

// 全局变量
static uart_state_t esp_uart_state;
static uint8_t rx_buffer[BUFFER_SIZE];
static volatile uint16_t rx_index                           = 0;
static volatile char expected_response[MAX_RESPONSE_LENGTH] = "";
static volatile ESP_Status at_command_status                = ESP_TIMEOUT;
static volatile bool response_complete                      = false;

// UART接收回调函数
void ESP_RxCallback(void *driverState, uart_event_t event, void *callbackParam)
{
    (void)driverState;
    (void)callbackParam;

    if (event == UART_EVENT_RX_FULL) {
        // 检查是否收到回车或换行符
        if ((rx_buffer[rx_index] == '\n') || (rx_buffer[rx_index] == '\r')) {
            // 添加字符串结束符
            if (rx_index < (BUFFER_SIZE - 1)) {
                rx_buffer[rx_index] = '\0';
            }
            log_info("ESP8266 RAW: %s \r\n", rx_buffer);
            // 检查是否包含预期响应
            if (expected_response[0] != '\0') {
                if (strstr((char *)rx_buffer, expected_response) != NULL) {
                    at_command_status = ESP_OK;
                    response_complete = true;
                } else if (strstr((char *)rx_buffer, "ERROR") != NULL) {
                    at_command_status = ESP_ERROR;
                    response_complete = true;
                }
            }

            // 重置缓冲区索引
            rx_index = 0;
        } else if (rx_index < (BUFFER_SIZE - 1)) {
            // 继续接收下一个字符
            rx_index++;
            UART_DRV_SetRxBuffer(ESP8266_UART_INSTANCE, &rx_buffer[rx_index], 1);
        } else {
            // 缓冲区满，重置
            rx_index = 0;
            UART_DRV_SetRxBuffer(ESP8266_UART_INSTANCE, rx_buffer, 1);
        }
    }
    UART_DRV_ReceiveData(ESP8266_UART_INSTANCE, rx_buffer, 1);
}

// 发送AT指令并等待响应
ESP_Status ESP_SendATCommand(const char *cmd, const char *expected_response_str, uint32_t timeout)
{
    // 重置状态
    response_complete = false;
    at_command_status = ESP_TIMEOUT;
    rx_index          = 0;
    memset(rx_buffer, 0, sizeof(rx_buffer));

    // 设置预期响应
    strncpy((char *)expected_response, expected_response_str, sizeof(expected_response) - 1);
    expected_response[sizeof(expected_response) - 1] = '\0';

    // 发送命令
    status_t status = UART_DRV_SendDataBlocking(ESP8266_UART_INSTANCE,
                                                (const uint8_t *)cmd,
                                                strlen(cmd),
                                                timeout);
    if (status != STATUS_SUCCESS) {
        return ESP_ERROR;
    }

    // 发送回车换行
    status = UART_DRV_SendDataBlocking(ESP8266_UART_INSTANCE,
                                       (const uint8_t *)"\r\n",
                                       2,
                                       timeout);
    if (status != STATUS_SUCCESS) {
        return ESP_ERROR;
    }

    // 等待响应
    uint32_t start_time = CLOCK_DRV_GetMilliseconds();
    uint32_t bytesRemaining;

    while (!response_complete) {
        // 检查超时
        if ((CLOCK_DRV_GetMilliseconds() - start_time) >= timeout) {
            at_command_status = ESP_TIMEOUT;
            break;
        }

        // 检查接收状态
        if (UART_DRV_GetReceiveStatus(ESP8266_UART_INSTANCE, &bytesRemaining) != STATUS_BUSY) {
            // 接收完成但未找到匹配响应
            at_command_status = ESP_TIMEOUT;
            break;
        }
    }

    // 清除预期响应
    expected_response[0] = '\0';

    return at_command_status;
}

// 初始化ESP8266
ESP_Status ESP8266_Init(void)
{
    UART_DRV_Init(ESP8266_UART_INSTANCE, &g_stUartState_1, &g_stUart1UserConfig0);
    // 测试AT指令
    UART_DRV_InstallRxCallback(ESP8266_UART_INSTANCE, ESP_RxCallback, NULL);

    // 启动接收（逐字节）
    UART_DRV_ReceiveData(ESP8266_UART_INSTANCE, rx_buffer, 1);
}

// 连接WiFi
ESP_Status ESP_ConnectToWiFi(void)
{
    char cmd[128];
    ESP_SendATCommand("AT+CWAUTOCONN=0", "OK", 2000);
    CLOCK_DRV_Delay(500);

    ESP_SendATCommand("AT+CWMODE=3", "OK", 2000);
    CLOCK_DRV_Delay(500);

    snprintf(cmd, sizeof(cmd), "AT+CWJAP=\"%s\",\"%s\"", WIFI_SSID, WIFI_PASSWORD);
    return ESP_SendATCommand(cmd, "WIFI CONNECTED", 10000);
}

// 连接TCP服务器
ESP_Status ESP_ConnectToTCPServer(void)
{
    char cmd[512];

    ESP_SendATCommand("AT+CIPMODE=1", "OK", 1000);
    CLOCK_DRV_Delay(500);

    snprintf(cmd, sizeof(cmd), "AT+CIPSTART=\"TCP\",\"%s\",%s", CLOUD_PLANTFORM, CLOUD_PORT);
    if (ESP_SendATCommand(cmd, "OK", 2000) != ESP_OK) {
        // return ESP_ERROR;
    }
    CLOCK_DRV_Delay(1500);

    if (ESP_SendATCommand("AT+CIPSEND", ">", 2000) != ESP_OK) {
        // return ESP_ERROR;
    }
    CLOCK_DRV_Delay(500);

    // 发送订阅命令
    snprintf(cmd, sizeof(cmd), "cmd=1&uid=%s&topic=%s", CLOUD_UID, CLOUD_TOPIC_POST1);
    if (ESP_SendATCommand(cmd, "cmd=1&res=1", 1000) != ESP_OK) {
        //        return ESP_ERROR;
    }
    CLOCK_DRV_Delay(1000);

    snprintf(cmd, sizeof(cmd), "cmd=1&uid=%s&topic=%s", CLOUD_UID, CLOUD_TOPIC_POST2);
    if (ESP_SendATCommand(cmd, "cmd=1&res=1", 1000) != ESP_OK) {
        // return ESP_ERROR;
    }
    CLOCK_DRV_Delay(1000);

    snprintf(cmd, sizeof(cmd), "cmd=1&uid=%s&topic=%s", CLOUD_UID, CLOUD_TOPIC_POST3);
    if (ESP_SendATCommand(cmd, "cmd=1&res=1", 1000) != ESP_OK) {
        // return ESP_ERROR;
    }
    CLOCK_DRV_Delay(1000);

    snprintf(cmd, sizeof(cmd), "cmd=1&uid=%s&topic=%s", CLOUD_UID, CLOUD_TOPIC_POST4);
    if (ESP_SendATCommand(cmd, "cmd=1&res=1", 1000) != ESP_OK) {
        // return ESP_ERROR;
    }
    CLOCK_DRV_Delay(1000);
    snprintf(cmd, sizeof(cmd), "cmd=1&uid=%s&topic=%s", CLOUD_UID, CLOUD_TOPIC_GET);
    if (ESP_SendATCommand(cmd, "cmd=1&res=1", 1000) != ESP_OK) {
        // return ESP_ERROR;
    }
    CLOCK_DRV_Delay(500);

    // 发送ping命令
    return ESP_SendATCommand("cmd=0&msg=ping", "cmd=0&res=1", 1000);
}

// 发送传感器数据
ESP_Status ESP_Send_Sensor_Data(float data1, float data2, float data3, uint16_t data4)
{
    char cmd[128];
    snprintf(cmd, sizeof(cmd), "cmd=2&uid=%s&topic=%s&msg=#%.3f#%.3f#%.3f#%d#AirTemp_AirHumi_GoodsTemp_CO2#", CLOUD_UID, CLOUD_TOPIC_POST1, data1,
             data2, data3, data4);
    return ESP_SendATCommand(cmd, "cmd=2&res=1", 1000);
}

ESP_Status ESP_Send_MPU6050_Data(float data1, float data2, float data3, float data4, float data5, float data6)
{
    char cmd[256];
    snprintf(cmd, sizeof(cmd), "cmd=2&uid=%s&topic=%s&msg=#%.3f#%.3f#%.3f#%.3f#%.3f#%.3f#aX_aY_aZ_gX_gY_gZ#", CLOUD_UID,
             CLOUD_TOPIC_POST2, data1, data2, data3, data4, data5, data6);
    return ESP_SendATCommand(cmd, "cmd=2&res=1", 1000);
}

ESP_Status ESP_Send_GPS_Data(float Longitude, float Latitude)
{
    char cmd[128];
    snprintf(cmd, sizeof(cmd), "cmd=2&uid=%s&topic=%s&msg=#%.3f#%.3f#Longitude_Latitude#", CLOUD_UID,
             CLOUD_TOPIC_POST3, Longitude, Latitude);
    return ESP_SendATCommand(cmd, "cmd=2&res=1", 1000);
}

ESP_Status ESP_Send_Count_Data(uint32_t OPEN_Door, uint32_t CLOSE_Door, uint32_t OPEN_Light, uint32_t Shock)
{
    char cmd[128];
    snprintf(cmd, sizeof(cmd), "cmd=2&uid=%s&topic=%s&msg=#%d#%d#%d#%d#OPENDoor_CLOSEDoor_Light_Shock#", CLOUD_UID,
             CLOUD_TOPIC_POST4, OPEN_Door, CLOSE_Door, OPEN_Light, Shock);
    return ESP_SendATCommand(cmd, "cmd=2&res=1", 1000);
}

// 发送字符串数据
ESP_Status ESP_SendString(const uint8_t *data, uint16_t len)
{
    char cmd[512];
    // 确保不超过缓冲区大小
    uint16_t copy_len = len < (sizeof(cmd) - 64) ? len : (sizeof(cmd) - 64);
    char safe_data[copy_len + 1];
    memcpy(safe_data, data, copy_len);
    safe_data[copy_len] = '\0';

    snprintf(cmd, sizeof(cmd), "cmd=2&uid=%s&topic=%s&msg=%s",
             CLOUD_UID, CLOUD_TOPIC_GET, safe_data);
    return ESP_SendATCommand(cmd, "cmd=2&res=1", 1000);
}

// 发送Ping
ESP_Status ESP_SendPing(void)
{
    return ESP_SendATCommand("cmd=0&msg=ping", "cmd=0&res=1", 5000);
}
